package com.ruoyi.web.controller.system;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ming.wx.*;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.model.WxLoginBody;
import com.ruoyi.framework.config.WechatConfig;
import com.ruoyi.framework.config.WechatGDConfig;
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
import com.ruoyi.framework.web.domain.server.Sys;
import com.ruoyi.framework.web.service.CommonRestTemplateService;
import com.ruoyi.framework.web.service.WeChatAuthorizeUtil;
import com.ruoyi.system.domain.MingUserconfig;
import com.ruoyi.system.service.IMingUserconfigService;
import com.ruoyi.system.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.AppleLoginBody;
import com.ruoyi.common.core.domain.model.AppleTokenPayload;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.AppleTokenVerificationService;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysMenuService;
import com.ruoyi.system.service.ISysRefreshTokenService;

import javax.annotation.Resource;

/**
 * 登录验证
 * 
 * @author ruoyi
 */
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Resource
    private CommonRestTemplateService templateService; //自己封装的restTemplate（在最后）

    @Resource
    private WeChatAuthorizeUtil weChatAuthorizeUtil;//授权工具类（在最后）

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IMingUserconfigService mingUserconfigService;

    @Autowired
    private AppleTokenVerificationService appleTokenVerificationService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ISysRefreshTokenService refreshTokenService;

    /**
     * JWT签名密钥 - 从配置文件获取
     */
    @org.springframework.beans.factory.annotation.Value("${token.secret}")
    private String jwtSecret;

//    @Resource
//    private WechatGDConfig wechatgdConfig;

    private Map<String, String> mymap = new HashMap<String,String>(){
        {
            put("news", "/system/mynews/query");
            put("weather", "/system/userconfig/queryWeather");
            put("stock", "/system/d/query");
            put("note", "/system/userconfig/queryNote");
            put("huangdao", "/system/answer/1");//huangdao,program,mingyan,xiaohua
            put("program", "/system/answer/2");
            put("mingyan", "/system/answer/3");
            put("xiaohua", "/system/answer/4");
            put("huanglib", "/system/answer/5");
        }
    };

    /**
     * 登录方法
     * 
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    @PostMapping("/loginNC")
    public AjaxResult loginNC(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        MingUserconfig userConf = new MingUserconfig();
        // 生成令牌
        String token = loginService.loginNC(loginBody.getUsername(), loginBody.getPassword(), loginBody.getUuid(),userConf);
//        SysUser user = SecurityUtils.getLoginUser().getUser();
        MingUserconfig myuserConf = mingUserconfigService.selectMingUserconfigById(userConf.getId());
        ajax.put(Constants.TOKEN, token);
        ajax.put("speed", myuserConf.getSpeed());
        ajax.put("period", myuserConf.getPeriod());
        String tmp = myuserConf.getNews();
        String rtVal = "";
        if (tmp!=null) {
            String [] arrs = tmp.split(",");
            int size = arrs.length;
            for (int i = 0; i < size; i++) {
                if (i==size-1) {
                    rtVal += mymap.get(arrs[i]);
                } else {
                    rtVal += mymap.get(arrs[i]) + ",";
                }
            }
        }
        if ("".equals(rtVal)) {
            rtVal = mymap.get("news")+","+mymap.get("weather")+","+mymap.get("stock")+","+mymap.get("note");
        }
        ajax.put("news", rtVal);
        boolean isupdate = true;
        if (StringUtils.isNotBlank(RuoYiConfig.getServerConfig())&&isupdate) {
            ajax.put("serverConf", RuoYiConfig.getServerConfig());
        }
        return ajax;
    }

    //问题宝箱登录入口
    @PostMapping("/wxlogin")
    public AjaxResult wxlogin(@RequestBody WxLoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        Code2SessionRespDTO respDTO = new Code2SessionRespDTO();

        //使用restTemplate调用调用微信提供的接口(auth.code2Session接口)
        ResponseEntity<String> responseEntity =
                templateService.getForEntity(weChatAuthorizeUtil.getCode2SessionUrl(loginBody.getCode()));
        if (responseEntity.getStatusCode().value() != HttpStatus.OK.value()) {
//            return RespResult.error(RespResultEnum.JS_CODE_REQ_ERROR);
            System.out.println("小程序调用异常错误！");
            return AjaxResult.error();
        }
        //获取微信“auth.code2Session接口”返回的信息，并封装到自己的DTO中（DTO在最后）
        WeiXinOAuthCode2SessionRespDTO code2SessionRespDTO =
                JSON.parseObject(responseEntity.getBody(), WeiXinOAuthCode2SessionRespDTO.class);
        if (StringUtils.isBlank(code2SessionRespDTO.getOpenid())) {
//            return RespResult.error(RespResultEnum.SESSION_KEY_ERROR.getCode(),
//                    RespResultEnum.SESSION_KEY_ERROR.getMessage() + code2SessionRespDTO.getErrmsg());
//            return null;
            System.out.println("小程序错误：");
            System.out.println(code2SessionRespDTO.getErrmsg());
            System.out.println(code2SessionRespDTO.getErrcode());
            return AjaxResult.error();
        }
        System.out.println(code2SessionRespDTO.getOpenid());
        String openId = code2SessionRespDTO.getOpenid();


//        return tokenService.createToken(loginUser);
        // 生成令牌
        String token = loginService.loginWx(code2SessionRespDTO);
        ajax.put(Constants.TOKEN, token);
        ajax.put("openid", code2SessionRespDTO.getOpenid());
        ajax.put("skey", code2SessionRespDTO.getSession_key());
        //获取昵称和头像 如果不为空则赋值
//        SysUser sysUser = userService.selectUserByUserName(openId);
//        if (StringUtils.isNotBlank(sysUser.getNickName())&&StringUtils.isNotBlank(sysUser.getAvatar())) {
        ajax.put("nickName", code2SessionRespDTO.getNickName());
        ajax.put("avatar", code2SessionRespDTO.getAvatar());
//        }
        return ajax;


//        AjaxResult ajax = AjaxResult.success();
//        ajax.put("openid", code2SessionRespDTO.getOpenid());
//        ajax.put("skey", code2SessionRespDTO.getSession_key());
//        return ajax;

//        return code2SessionRespDTO.getOpenid();

//        AjaxResult ajax = AjaxResult.success();
//         生成令牌
//        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
//                loginBody.getUuid());
//        ajax.put(Constants.TOKEN, token);
//        return ajax;
    }

    //极客桌面登录入口
    @PostMapping("/wxlogingd")
    public AjaxResult wxlogingd(@RequestBody WxLoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        Code2SessionRespDTO respDTO = new Code2SessionRespDTO();

        //使用restTemplate调用调用微信提供的接口(auth.code2Session接口)
        ResponseEntity<String> responseEntity =
                templateService.getForEntity(weChatAuthorizeUtil.getGDCode2SessionUrl(loginBody.getCode()));
        if (responseEntity.getStatusCode().value() != HttpStatus.OK.value()) {
//            return RespResult.error(RespResultEnum.JS_CODE_REQ_ERROR);
            System.out.println("小程序调用异常错误！");
            return AjaxResult.error();
        }
        //获取微信“auth.code2Session接口”返回的信息，并封装到自己的DTO中（DTO在最后）
        WeiXinOAuthCode2SessionRespDTO code2SessionRespDTO =
                JSON.parseObject(responseEntity.getBody(), WeiXinOAuthCode2SessionRespDTO.class);
        if (StringUtils.isBlank(code2SessionRespDTO.getOpenid())) {
//            return RespResult.error(RespResultEnum.SESSION_KEY_ERROR.getCode(),
//                    RespResultEnum.SESSION_KEY_ERROR.getMessage() + code2SessionRespDTO.getErrmsg());
//            return null;
            System.out.println("小程序错误：");
            System.out.println(code2SessionRespDTO.getErrmsg());
            System.out.println(code2SessionRespDTO.getErrcode());
            return AjaxResult.error();
        }
        System.out.println(code2SessionRespDTO.getOpenid());
        String openId = code2SessionRespDTO.getOpenid();

        //改造从前端获取用户名称和头像
        if (StringUtils.isBlank(code2SessionRespDTO.getNickName())&&StringUtils.isNotBlank(loginBody.getNickName())&&!"微信用户".equals(loginBody.getNickName())) {
            code2SessionRespDTO.setNickName(loginBody.getNickName());
        }

        if (StringUtils.isBlank(code2SessionRespDTO.getAvatar())&&StringUtils.isNotBlank(loginBody.getAvatarUrl())&&!"微信用户".equals(loginBody.getNickName())) {
            code2SessionRespDTO.setAvatar(loginBody.getAvatarUrl());
        }

//        return tokenService.createToken(loginUser);
        // 生成令牌
        String token = loginService.loginWx(code2SessionRespDTO);
        ajax.put(Constants.TOKEN, token);
        ajax.put("openid", code2SessionRespDTO.getOpenid());
        ajax.put("skey", code2SessionRespDTO.getSession_key());

        /*ResponseEntity<String> responseToken =
                templateService.getForEntity("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + wechatgdConfig.getAppId() + "&secret=" + wechatgdConfig.getSecretKey());

        JSONObject jsonObject = JSONObject.parseObject(responseToken.getBody());
        ResponseEntity<String> responseNickName  =
                templateService.getForEntity("https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + jsonObject.getString("access_token") + "&openid=" + code2SessionRespDTO.getOpenid() + "&lang=zh_CN");*/
        //获取昵称和头像 如果不为空则赋值
//        SysUser sysUser = userService.selectUserByUserName(openId);
//        if (StringUtils.isNotBlank(sysUser.getNickName())&&StringUtils.isNotBlank(sysUser.getAvatar())) {
        ajax.put("nickName", code2SessionRespDTO.getNickName());
        ajax.put("avatar", code2SessionRespDTO.getAvatar());
//        }
        return ajax;


//        AjaxResult ajax = AjaxResult.success();
//        ajax.put("openid", code2SessionRespDTO.getOpenid());
//        ajax.put("skey", code2SessionRespDTO.getSession_key());
//        return ajax;

//        return code2SessionRespDTO.getOpenid();

//        AjaxResult ajax = AjaxResult.success();
//         生成令牌
//        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
//                loginBody.getUuid());
//        ajax.put(Constants.TOKEN, token);
//        return ajax;
    }

    /**
     * 获取用户信息
     * 
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    /**
     * Apple登录方法
     *
     * @param loginBody Apple登录信息
     * @return 结果
     */
    @PostMapping("/apple_login")
    public AjaxResult appleLogin(@RequestBody Map<String, String> loginBody)
    {
        // 获取客户端IP
        String clientIp = com.ruoyi.common.utils.ip.IpUtils.getIpAddr(com.ruoyi.common.utils.ServletUtils.getRequest());

        try
        {
            String identityToken = loginBody.get("identityToken");
            String refreshToken = loginBody.get("refreshToken");

            // 记录Apple登录请求
            if (StringUtils.isNotEmpty(identityToken)) {
                System.out.println("🍎 [Apple登录] 收到identityToken登录请求，客户端IP: " + clientIp);
                System.out.println("🍎 [Apple登录] identityToken长度: " + identityToken.length() + " 字符");
            } else if (StringUtils.isNotEmpty(refreshToken)) {
                System.out.println("🔄 [Apple刷新] 收到refreshToken刷新请求，客户端IP: " + clientIp);
                System.out.println("🔄 [Apple刷新] refreshToken长度: " + refreshToken.length() + " 字符");
            }

            if (StringUtils.isNotEmpty(refreshToken))
            {
                // 使用refresh_token刷新
                return refreshTokenLogin(refreshToken);
            }
            else if (StringUtils.isNotEmpty(identityToken))
            {
                // 使用Apple identityToken登录
                return loginWithAppleIdentityToken(identityToken);
            }
            else
            {
                System.out.println("❌ [Apple登录] 请求失败：缺少必要的认证信息，客户端IP: " + clientIp);
                return AjaxResult.error("缺少必要的认证信息");
            }
        }
        catch (Exception e)
        {
            System.out.println("❌ [Apple登录] 系统异常，客户端IP: " + clientIp + "，错误: " + e.getMessage());
            e.printStackTrace();
            return AjaxResult.error("Apple登录失败: " + e.getMessage());
        }
    }

    /**
     * 使用Apple Identity Token登录
     *
     * @param identityToken Apple Identity Token
     * @return 登录结果
     */
    private AjaxResult loginWithAppleIdentityToken(String identityToken)
    {
        try
        {
            System.out.println("🔍 [Apple验证] 开始验证Apple Identity Token...");

            // 验证Apple identityToken
            AppleTokenPayload payload = appleTokenVerificationService.verifyAppleToken(identityToken);
            System.out.println("✅ [Apple验证] Token验证成功！Apple用户ID: " + payload.getSub());
            if (payload.getEmail() != null) {
                System.out.println("📧 [Apple验证] 用户邮箱: " + payload.getEmail());
            }

            System.out.println("👤 [用户管理] 开始查找或创建Apple用户...");

            // 查找或创建用户
            SysUser user = findOrCreateAppleUser(payload);
            System.out.println("✅ [用户管理] 用户处理完成！用户ID: " + user.getUserId() + "，用户名: " + user.getUserName());

            System.out.println("🔑 [Token生成] 开始生成访问令牌...");

            // 生成JWT token和refresh token
            LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
            String accessToken = tokenService.createToken(loginUser);

            // 生成refresh token (30天过期)
            long refreshExpireSeconds = 30 * 24 * 60 * 60; // 30天
            String refreshToken = refreshTokenService.generateRefreshToken(user.getUserId(), refreshExpireSeconds);

            System.out.println("🔑 [Token生成] 访问令牌生成成功，长度: " + accessToken.length() + " 字符");
            System.out.println("🔄 [Token生成] 刷新令牌生成成功，有效期: 30天");

            // 保存refresh token到数据库
            refreshTokenService.saveOrUpdateRefreshToken(user.getUserId(), refreshToken,
                new java.util.Date(System.currentTimeMillis() + refreshExpireSeconds * 1000));

            System.out.println("💾 [数据库] 刷新令牌已保存到数据库");

            // 记录登录信息
            recordAppleLoginInfo(user.getUserId());

            // 成功登录的祝贺日志
            System.out.println("🎉🎉🎉 [Apple登录成功] 恭喜！用户登录成功！🎉🎉🎉");
            System.out.println("🏆 [登录详情] 用户ID: " + user.getUserId() + "，昵称: " + user.getNickName());
            System.out.println("🏆 [登录详情] Apple用户ID: " + user.getAppleUserId());
            System.out.println("🏆 [登录详情] 登录时间: " + new java.util.Date());
            System.out.println("🎊 [Apple登录] ======== 登录流程全部完成 ========");

            AjaxResult ajax = AjaxResult.success("🎉 恭喜！Apple登录成功！欢迎使用 mynews3 应用！");
            ajax.put(Constants.TOKEN, accessToken);
            ajax.put("refreshToken", refreshToken);
            ajax.put("user", user);
            ajax.put("welcomeMessage", "🍎 欢迎通过Apple ID登录！");
            ajax.put("loginTime", new java.util.Date());
            return ajax;
        }
        catch (Exception e)
        {
            System.out.println("❌ [Apple登录失败] 详细错误信息: " + e.getMessage());
            e.printStackTrace();
            return AjaxResult.error("Apple Token验证失败: " + e.getMessage());
        }
    }

    /**
     * 使用Refresh Token刷新访问令牌
     *
     * @param refreshToken Refresh Token
     * @return 刷新结果
     */
    private AjaxResult refreshTokenLogin(String refreshToken)
    {
        try
        {
            // 验证refresh token
            io.jsonwebtoken.Claims claims = io.jsonwebtoken.Jwts.parser()
                    .setSigningKey(jwtSecret)
                    .parseClaimsJws(refreshToken)
                    .getBody();

            Long userId = Long.parseLong(claims.getSubject());

            // 检查数据库中的refresh token
            if (!refreshTokenService.isValidRefreshToken(userId, refreshToken))
            {
                return AjaxResult.error("refresh_token无效或已过期");
            }

            // 获取用户信息
            SysUser user = userService.selectUserById(userId);
            if (user == null)
            {
                return AjaxResult.error("用户不存在");
            }

            // 生成新的访问token
            LoginUser loginUser = new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
            String newAccessToken = tokenService.createToken(loginUser);

            // 记录登录信息
            recordAppleLoginInfo(user.getUserId());

            AjaxResult ajax = AjaxResult.success("Token刷新成功");
            ajax.put(Constants.TOKEN, newAccessToken);
            ajax.put("refreshToken", refreshToken); // 返回原refresh token
            ajax.put("user", user);
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error("Token刷新失败: " + e.getMessage());
        }
    }

    /**
     * 查找或创建Apple用户
     *
     * @param payload Apple Token载荷
     * @return 用户信息
     */
    private SysUser findOrCreateAppleUser(AppleTokenPayload payload)
    {
        // 先通过Apple User ID查找
        SysUser user = userService.selectUserByAppleId(payload.getSub());

        if (user == null)
        {
            // 创建新用户
            user = new SysUser();
            user.setAppleUserId(payload.getSub());
            user.setUserName(payload.getSub()); // 使用Apple ID作为用户名
            user.setNickName(payload.getEmail() != null ?
                payload.getEmail().split("@")[0] : "Apple用户_" + payload.getSub().substring(0, 8));
            user.setEmail(payload.getEmail());
            user.setPassword(SecurityUtils.encryptPassword("apple_user_default_" + payload.getSub())); // 生成默认密码
            user.setRoleIds(new Long[]{4L}); // Apple用户默认角色
            user.setCreateBy("apple_signin");
            user.setStatus("0"); // 正常状态
            user.setSex("2"); // 未知性别
            user.setDeptId(103L); // 默认部门，根据实际情况调整

            userService.insertUser(user);
        }
        else
        {
            // 更新用户邮箱（如果有变化）
            if (payload.getEmail() != null && !payload.getEmail().equals(user.getEmail()))
            {
                user.setEmail(payload.getEmail());
                userService.updateUser(user);
            }
        }

        return user;
    }

    /**
     * 记录Apple登录信息
     *
     * @param userId 用户ID
     */
    private void recordAppleLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setLoginIp(com.ruoyi.common.utils.ip.IpUtils.getIpAddr(com.ruoyi.common.utils.ServletUtils.getRequest()));
        sysUser.setLoginDate(com.ruoyi.common.utils.DateUtils.getNowDate());
        userService.updateUserProfile(sysUser);

        // 异步记录登录日志
        com.ruoyi.framework.manager.AsyncManager.me().execute(
            com.ruoyi.framework.manager.factory.AsyncFactory.recordLogininfor(
                "apple_user_" + userId, Constants.LOGIN_SUCCESS, "Apple登录成功"));
    }
}
